package appcus

import (
	"counter-help/admin/server/global"
	"counter-help/admin/server/model/app"
	"counter-help/admin/server/model/common/response"
	"counter-help/admin/server/model/customer"
	"crypto/aes"
	"crypto/cipher"
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-resty/resty/v2"
	"io/ioutil"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"time"
)

// CusOrderPayApi 小程序订单支付功能
type AppCusOrderPayApi struct{}

const (
	//ApiKeyv3  = "CDtongjisuisuinian202312shanglue"
	ApiKeyv2 = "CDshanglue202312tongjisuisuinian"
	AppID    = "wx397aa4c18c836e69"
	MchID    = "1694609563"
	//NotifyURL   = "https://web.tjbbb.com/api/appCusOrderPay/notify"   // 支付回调地址
	WxNotifyURL = "https://web.tjbbb.com/api/appCusOrderPay/wxnotify" // 支付回调地址
)

// AppOrderPay 微信订单支付
func (p *AppCusOrderPayApi) AppOrderPay(c *gin.Context) {
	// 获取订单 和 订单价格
	var orderReq app.OrderRequest
	if err := c.ShouldBindJSON(&orderReq); err != nil {
		global.GVA_LOG.Error("Invalid request::" + err.Error())
		response.FailWithMessage("Invalid request::"+err.Error(), c)
		return
	}

	// 生成统一下单请求的参数
	params := map[string]string{
		"appid":            AppID,
		"mch_id":           MchID,
		"nonce_str":        generateNonceStr(),
		"body":             orderReq.Body,
		"out_trade_no":     orderReq.OutTradeNo,
		"total_fee":        fmt.Sprintf("%d", orderReq.TotalFee),
		"spbill_create_ip": "139.162.62.102", // 服务器IP
		"notify_url":       WxNotifyURL,
		"trade_type":       "JSAPI", // 小程序支付
		"sign_type":        "MD5",
		"openid":           orderReq.OpenID,
	}

	// 生成签名
	sign := generateSign(params, ApiKeyv2)
	params["sign"] = sign

	// 生成XML请求体
	xmlRequest, err := generateXMLRequest(params)
	if err != nil {
		global.GVA_LOG.Error("生成XML请求失败 Error::" + err.Error())
		response.FailWithMessage("生成XML请求失败 Error::"+err.Error(), c)
		return
	}

	// 向微信支付发起请求
	client := resty.New()
	resp, err := client.R().
		SetHeader("Content-Type", "application/xml").
		SetBody(xmlRequest).
		Post("https://api.mch.weixin.qq.com/pay/unifiedorder")
	if err != nil {
		global.GVA_LOG.Error("与微信通信失败 Error::" + err.Error())
		response.FailWithMessage("与微信通信失败 Error::"+err.Error(), c)
		return
	}

	// 解析微信支付返回的数据
	var unifiedOrderResp app.UnifiedOrderResponse
	err = xml.Unmarshal(resp.Body(), &unifiedOrderResp)
	if err != nil {
		global.GVA_LOG.Error("解析微信返回失败 Error::" + err.Error())
		response.FailWithMessage("解析微信返回失败 Error::"+err.Error(), c)
		return
	}

	// 如果返回成功，返回预支付ID
	if unifiedOrderResp.ReturnCode == "SUCCESS" {
		if unifiedOrderResp.ResultCode != "SUCCESS" {
			global.GVA_LOG.Error("微信业务错误: " + unifiedOrderResp.ErrCode + " - " + unifiedOrderResp.ErrCodeDes)
			response.FailWithMessage("支付失败: "+unifiedOrderResp.ErrCodeDes, c)
			return
		}
		// 前端需要的支付参数
		timestamp := fmt.Sprintf("%d", time.Now().Unix())
		pkg := "prepay_id=" + unifiedOrderResp.PrepayID

		// 生成签名
		paramsGenOrder := map[string]string{
			"appId":     AppID,
			"package":   pkg,
			"nonceStr":  unifiedOrderResp.NonceStr,
			"timeStamp": timestamp,
			"signType":  "MD5",
		}

		paySign := generateSign(paramsGenOrder, ApiKeyv2)
		paramsGenOrder["paySign"] = paySign

		// 返回预支付交易会话标识
		response.OkWithDetailed(paramsGenOrder, "微信预订单创建成功", c)
	} else {
		global.GVA_LOG.Error("解析微信返回失败 Error::" + unifiedOrderResp.ReturnMsg)
		response.FailWithMessage("解析微信返回失败 Error::"+unifiedOrderResp.ReturnMsg, c)
		return
	}

}

// 解密函数

func Decrypt(ciphertext, associatedData, nonce, apiV3Key string) (string, error) {
	// 1. Base64 解码
	ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertext)
	if err != nil {
		return "", err
	}

	// 2. 生成 AES 密钥
	aesKey := []byte(apiV3Key)

	// 3. 创建 AES-GCM
	block, err := aes.NewCipher(aesKey)
	if err != nil {
		return "", err
	}
	aesGCM, err := cipher.NewGCM(block)
	if err != nil {
		return "", err
	}

	// 4. 解密
	plaintext, err := aesGCM.Open(nil, []byte(nonce), ciphertextBytes, []byte(associatedData))
	if err != nil {
		return "", err
	}

	return string(plaintext), nil
}

// // 微信支付回调解密
//
//	func NewDecrypt(c *gin.Context) (notifyReq *notify.Request, err error) {
//		var (
//			mchCertificateSerialNumber = global.GVA_CONFIG.Wxpay.MchCertificateSerialNumber // 商户证书序列号
//			privateKeyPath             = global.GVA_CONFIG.Wxpay.PemPath                    // 商户私钥文件
//		)
//		fmt.Println("KKKKKKKKKK", MchID, ApiKeyv2, mchCertificateSerialNumber, privateKeyPath)
//		ctx := c             //这个参数是context.Background()
//		request := c.Request //这个值是*http.Request
//		// 使用 utils 提供的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
//		mchPrivateKey, err := utils.LoadPrivateKeyWithPath(privateKeyPath)
//		if err != nil {
//			return nil, err
//		}
//		err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(ctx, mchPrivateKey, mchCertificateSerialNumber, MchID, ApiKeyv2)
//		if err != nil {
//			return nil, err
//		}
//		// 2. 获取商户号对应的微信支付平台证书访问器
//		certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(MchID)
//		// 3. 使用证书访问器初始化 `notify.Handler`
//		handler := notify.NewNotifyHandler(ApiKeyv2, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
//
//		transaction := new(payments.Transaction)
//		notifyReq, err = handler.ParseNotifyRequest(ctx, request, transaction)
//		// 如果验签未通过，或者解密失败
//		if err != nil {
//			fmt.Println(err)
//			//return
//		}
//		// 处理通知内容
//		fmt.Println(notifyReq.Summary)
//		fmt.Println(transaction.TransactionId)
//		// 如果验签未通过，或者解密失败
//		if err != nil {
//			return nil, err
//		}
//		return notifyReq, nil
//	}
//
//	func (p *AppCusOrderPayApi) HandlePaymentNotification(c *gin.Context) {
//		var notifyDataEncrypt app.PaymentEncryptNotification
//
//		var notifyData app.PaymentResponse
//
//		var order customer.CusOrder
//		////// 获取原始请求体
//		//body, err := c.GetRawData()
//		//if err != nil {
//		//	c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取请求体"})
//		//	return
//		//}
//		// 如果绑定失败，尝试绑定 JSON 数据
//		if err := c.ShouldBindJSON(&notifyDataEncrypt); err != nil {
//			c.XML(http.StatusBadRequest, gin.H{"return_code": "FAIL", "return_msg": "Invalid data format"})
//			return
//		}
//		//fmt.Println("请求体内容:", string(body)) // 打印请求体内容
//		//if err := c.ShouldBindXML(&notifyDataEncrypt); err != nil {
//		//	// 如果绑定失败，尝试绑定 JSON 数据
//		//	if err := c.ShouldBindJSON(&notifyDataEncrypt); err != nil {
//		//		c.XML(http.StatusBadRequest, gin.H{"return_code": "FAIL", "return_msg": "Invalid data format"})
//		//		return
//		//	}
//		//}
//		//处理支付成功的逻辑
//		if notifyDataEncrypt.EventType == "TRANSACTION.SUCCESS" {
//			// 解密 resource 字段
//			plaintext, err := Decrypt(notifyDataEncrypt.Resource.Ciphertext, notifyDataEncrypt.Resource.AssociatedData, notifyDataEncrypt.Resource.Nonce, global.GVA_CONFIG.Wxpay.MchAPIv3Key) // 替换为你的 API v3 密钥
//			if err != nil {
//				fmt.Println("解密失败:", err)
//				c.XML(http.StatusInternalServerError, gin.H{"error": "Decryption failed"})
//				return
//			}
//			fmt.Println("解密后数据", plaintext)
//			// 解析 JSON 数据
//			if err := json.Unmarshal([]byte(plaintext), &notifyData); err != nil {
//				fmt.Println("解析 JSON 失败:", err)
//				return
//			}
//			//// 准备签名参数
//			//params := map[string]string{
//			//	"appid":          notifyData.AppID,
//			//	"bank_type":      notifyData.BankType,
//			//	"cash_fee":       notifyData.CashFee,
//			//	"fee_type":       notifyData.FeeType,
//			//	"is_subscribe":   notifyData.IsSubscribe,
//			//	"mch_id":         notifyData.MchID,
//			//	"nonce_str":      notifyData.NonceStr,
//			//	"openid":         notifyData.Openid,
//			//	"out_trade_no":   notifyData.OutTradeNo,
//			//	"result_code":    notifyData.ResultCode,
//			//	"return_code":    notifyData.ReturnCode,
//			//	"time_end":       notifyData.TimeEnd,
//			//	"total_fee":      notifyData.TotalFee,
//			//	"trade_type":     notifyData.TradeType,
//			//	"transaction_id": notifyData.TransactionID,
//			//}
//
//			////计算签名
//			//expectedSign := generateSign(params, global.GVA_CONFIG.Wxpay.MchAPIv3Key)
//			//
//			//// 验证签名
//			//if notifyData.Sign != expectedSign {
//			//	fmt.Println("微信支付回调 签名验证失败")
//			//	c.XML(http.StatusForbidden, gin.H{"return_code": "FAIL", "return_msg": "签名验证失败"})
//			//	return
//			//}
//
//			fmt.Println("微信支付回调 666666666666", notifyData)
//			// 返回处理结果
//			if notifyData.ReturnCode == "SUCCESS" && notifyData.ResultCode == "SUCCESS" {
//				orderId := getPrefixBeforeFirstUnderscore(notifyData.OutTradeNo)
//				fmt.Println("微信支付回调 签名验证失败" + orderId)
//				fee := notifyData.TotalFee
//				if strings.HasPrefix(orderId, "SN") {
//					if err := global.GVA_DB.Model(&customer.CusOrder{}).Where("order_no = ?", orderId).First(&order).Error; err != nil {
//						c.XML(http.StatusOK, gin.H{"return_code": "FAIL", "return_msg": "支付失败"})
//					}
//					orderId = string(order.ID)
//				}
//				dbErr := appOrderPayService.AppOrderPay(orderId, fee)
//				if dbErr != nil {
//					// 支付失败逻辑
//					c.XML(http.StatusOK, gin.H{"return_code": "FAIL", "return_msg": "支付失败"})
//				}
//				c.XML(http.StatusOK, gin.H{"return_code": "SUCCESS", "return_msg": "OK"})
//			} else {
//				fmt.Println("微信支付回调 支付失败")
//				// 支付失败逻辑
//				c.XML(http.StatusOK, gin.H{"return_code": "FAIL", "return_msg": "支付失败"})
//			}
//
//		} else {
//			fmt.Println("未处理的事件类型:", notifyDataEncrypt.EventType)
//		}
//
//}

func (p *AppCusOrderPayApi) HandleWxPaymentNotification(c *gin.Context) {
	fmt.Println("小程序微信支付开始回调")
	body, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		fmt.Println("读取请求体失败")
		c.String(http.StatusBadRequest, "读取请求体失败")
		return
	}
	defer c.Request.Body.Close()
	// 记录原始回调数据（用于调试）
	fmt.Println("微信支付回调原始数据：%s", string(body))
	var notifyData app.PaymentNotification

	if err := xml.Unmarshal(body, &notifyData); err != nil {
		c.XML(http.StatusBadRequest, gin.H{"return_code": "FAIL", "return_msg": "Invalid data format"})
		return
	}
	//var order customer.CusOrder
	// 3. 验证签名
	//if !verifyWechatSign(body, ApiKeyv2) {
	//	fmt.Println("签名验证失败")
	//	c.XML(http.StatusBadRequest, gin.H{"return_code": "FAIL", "return_msg": "Invalid data format"})
	//	return
	//}
	// 4. 处理业务逻辑
	if notifyData.ReturnCode == "SUCCESS" && notifyData.ResultCode == "SUCCESS" {
		// 转换金额（分 -> 元）
		totalFeeInt, err := strconv.Atoi(notifyData.TotalFee)
		if err != nil {
			fmt.Println("金额转换失败：%v", err)
			c.XML(http.StatusOK, gin.H{"return_code": "FAIL", "return_msg": "金额格式错误"})
			return
		}
		amount := float64(totalFeeInt) / 100.0
		amountStr := fmt.Sprintf("%.2f", amount) // 保留两位小数
		orderId := getPrefixBeforeFirstUnderscore(notifyData.OutTradeNo)
		dbErr := appOrderPayService.AppOrderPay(orderId, amountStr)
		if dbErr != nil {
			// 支付失败逻辑
			c.XML(http.StatusOK, gin.H{"return_code": "FAIL", "return_msg": "支付失败"})
		}
		c.XML(http.StatusOK, gin.H{"return_code": "SUCCESS", "return_msg": "OK"})
	} else {
		c.XML(http.StatusOK, gin.H{"return_code": "FAIL", "return_msg": "支付失败"})
	}

}

//// 验证微信签名
//func verifyWechatSign(body []byte, apiKey string) bool {
//	// 解析 XML 到 map
//	var params map[string]string
//	if err := xml.Unmarshal(body, &params); err != nil {
//		return false
//	}
//
//	// 获取微信回调的签名
//	receivedSign := params["sign"]
//	delete(params, "sign") // 移除签名字段
//
//	// 生成本地签名
//	var keys []string
//	for k := range params {
//		keys = append(keys, k)
//	}
//	sort.Strings(keys)
//
//	var signStr string
//	for _, k := range keys {
//		if params[k] != "" {
//			signStr += fmt.Sprintf("%s=%s&", k, params[k])
//		}
//	}
//	signStr += "key=" + apiKey
//
//	hash := md5.Sum([]byte(signStr))
//	generatedSign := strings.ToUpper(hex.EncodeToString(hash[:]))
//
//	return receivedSign == generatedSign
//}

func (p *AppCusOrderPayApi) HandlePaymentNotification(c *gin.Context) {
	var notifyDataEncrypt app.PaymentEncryptNotification

	var notifyData app.PaymentResponse
	var order customer.CusOrder
	////// 获取原始请求体
	//body, err := c.GetRawData()
	//if err != nil {
	//	c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取请求体"})
	//	return
	//}
	// 如果绑定失败，尝试绑定 JSON 数据
	if err := c.ShouldBindJSON(&notifyDataEncrypt); err != nil {
		c.XML(http.StatusBadRequest, gin.H{"return_code": "FAIL", "return_msg": "Invalid data format"})
		return
	}
	//fmt.Println("请求体内容:", string(body)) // 打印请求体内容
	//if err := c.ShouldBindXML(&notifyDataEncrypt); err != nil {
	//	// 如果绑定失败，尝试绑定 JSON 数据
	//	if err := c.ShouldBindJSON(&notifyDataEncrypt); err != nil {
	//		c.XML(http.StatusBadRequest, gin.H{"return_code": "FAIL", "return_msg": "Invalid data format"})
	//		return
	//	}
	//}
	//处理支付成功的逻辑
	if notifyDataEncrypt.EventType == "TRANSACTION.SUCCESS" {
		// 解密 resource 字段
		plaintext, err := Decrypt(notifyDataEncrypt.Resource.Ciphertext, notifyDataEncrypt.Resource.AssociatedData, notifyDataEncrypt.Resource.Nonce, global.GVA_CONFIG.Wxpay.MchAPIv3Key) // 替换为你的 API v3 密钥
		if err != nil {
			fmt.Println("解密失败:", err)
			c.XML(http.StatusInternalServerError, gin.H{"error": "Decryption failed"})
			return
		}
		fmt.Println("解密后数据", plaintext)
		// 解析 JSON 数据
		if err := json.Unmarshal([]byte(plaintext), &notifyData); err != nil {
			fmt.Println("解析 JSON 失败:", err)
			return
		}
		// 返回处理结果
		if notifyData.TradeState == "SUCCESS" {
			orderId := getPrefixBeforeFirstUnderscore(notifyData.OutTradeNo)
			fee := notifyData.Amount.Total
			amount := float64(fee) / 100.0           // 转换为元
			amountStr := fmt.Sprintf("%.2f", amount) // 保留两位小数
			if strings.HasPrefix(orderId, "SN") {
				if err := global.GVA_DB.Debug().Model(&customer.CusOrder{}).Where("order_no = ?", orderId).First(&order).Error; err != nil {
					c.XML(http.StatusOK, gin.H{"return_code": "FAIL", "return_msg": "支付失败"})
				}
				orderId = fmt.Sprintf("%d", order.ID)
			}
			dbErr := appOrderPayService.AppOrderPay(orderId, amountStr)
			if dbErr != nil {
				// 支付失败逻辑
				c.XML(http.StatusOK, gin.H{"return_code": "FAIL", "return_msg": "支付失败"})
			}
			c.XML(http.StatusOK, gin.H{"return_code": "SUCCESS", "return_msg": "OK"})
		} else {
			fmt.Println("微信支付回调 支付失败")
			// 支付失败逻辑
			c.XML(http.StatusOK, gin.H{"return_code": "FAIL", "return_msg": "支付失败"})
		}

	} else {
		fmt.Println("未处理的事件类型:", notifyDataEncrypt.EventType)
	}
}

// 生成随机字符串
func generateNonceStr() string {
	return fmt.Sprintf("%d", time.Now().UnixNano())
}

// 生成签名
func generateSign(params map[string]string, apiKey string) string {
	var keys []string
	for key := range params {
		// 排除 sign 参数本身
		if key != "sign" {
			keys = append(keys, key)
		}
	}

	// 排序参数
	sort.Strings(keys)

	var paramStr string
	for _, key := range keys {
		paramStr += key + "=" + params[key] + "&"
	}
	paramStr += "key=" + apiKey // 最后加上 API 密钥

	// 使用 MD5 加密并转为大写
	return md5Hash(paramStr)
}

// MD5 加密
func md5Hash(s string) string {
	hash := md5.New()
	hash.Write([]byte(s))
	return strings.ToUpper(hex.EncodeToString(hash.Sum(nil)))
}

// 生成XML请求体
func generateXMLRequest(params map[string]string) (string, error) {
	xmlStr := "<xml>"
	for key, value := range params {
		xmlStr += fmt.Sprintf("<%s>%s</%s>", key, value, key)
	}
	xmlStr += "</xml>"
	return xmlStr, nil
}

func getPrefixBeforeFirstUnderscore(input string) string {
	// 找到第一个下划线的位置
	index := strings.Index(input, "_")
	// 如果找到下划线，返回下划线前的子字符串；否则返回整个字符串
	if index != -1 {
		return input[:index]
	}
	return input
}
